package com.its.common.util;

import com.its.common.model.GeoJsonObj;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @Classname GeometryUtil
 * @Description shape工具转换类
 * @Date 2018/12/3 14:06
 * @Created by xiaxp
 */

public class GeometryUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(GeometryUtil.class);
    public static class GeometryType{
        static String POINT = "point";
        static String LINE = "line";
        static String POLYGON = "polygon";

    }
    /**
     * geo空间类型转openlayer：点位
     * @param geoPoint
     * @return
     */
    public static  Map<String, Object>  geoPoint2OL(String geoPoint) {
        Map<String, Object> geometryShape=new HashMap<String, Object>();
        if(null==geoPoint||"".equals(geoPoint)){
            return null;
        }
        String geoPointPattern = "POINT \\((.*?)\\)";
        String result = new GeometryUtil().getSubUtilSimple(geoPoint, geoPointPattern);
        if ("".equals(result)) {
            LOGGER.debug("未匹配到点位信息");
            return null;
        }
        String[] str1 = result.trim().split(" ");

        Float[] olString = new Float[]{Float.parseFloat(str1[0]),Float.parseFloat(str1[1])};
        geometryShape.put("type", "Point");
        geometryShape.put("coordinates", olString);
        return geometryShape;
    }


    /**
     * geo空间类型转openlayer：线段
     * @param geoLine
     * @return
     */
    public static Map<String, Object> geoLine2OL(String geoLine) {
        Map<String, Object> geometryShape=new HashMap<String, Object>();
        if(null==geoLine||"".equals(geoLine)){
            return null;
        }
        String geoMultLinePattern = "MULTILINESTRING \\(\\((.*?)\\)\\)";
        String multResult = new GeometryUtil().getSubUtilSimple(geoLine, geoMultLinePattern);
        if("".equals(multResult)){
            String geoLinePattern = "LINESTRING \\((.*?)\\)";
            String result = new GeometryUtil().getSubUtilSimple(geoLine, geoLinePattern);
            if ("".equals(result)) {
                LOGGER.debug("未匹配到点位信息");
                return null;
            }
            String[] str1 = result.split(",");
            List<Float[]> stringList=new ArrayList<Float[]>();
            for (int i = 0; i < str1.length; i++) {
                String[] x=str1[i].trim().split(" ");
                stringList.add(new Float[]{Float.parseFloat(x[0]),Float.parseFloat(x[1])});
            }
            geometryShape.put("type", "LineString");
            geometryShape.put("coordinates", stringList);
        }
        else {
            String[] str1 = multResult.split("\\), \\(");
            List<List<Float[]>>  shapeList=new ArrayList<>();
            for (int i = 0; i < str1.length; i++) {
                List<Float[]> stringList=new ArrayList<Float[]>();
                String[] str2 = str1[i].split(",");
                for (int j = 0; j <str2.length ; j++) {
                    String[] x=str2[j].trim().split(" ");
                    stringList.add(new Float[]{Float.parseFloat(x[0]),Float.parseFloat(x[1])});
                }
                shapeList.add(stringList);
            }
            geometryShape.put("type", "MultiLineString");
            geometryShape.put("coordinates", shapeList);
        }

        return geometryShape;
    }
    /**
     * geo空间类型转openlayer：圆形
     * @param circle
     * @return
     */
    public static Map<String, Object> circle2OL(String circle) {
        Map<String, Object> geometryShape=new HashMap<String, Object>();
        String geoCurvePolygonPattern = "CURVEPOLYGON \\(COMPOUNDCURVE \\(CIRCULARSTRING \\(((.*?))\\)\\)\\)";
        String curveResult = new GeometryUtil().getSubUtilSimple(circle, geoCurvePolygonPattern);
        String[] str1 = curveResult.split(",");
        List<Float[]> stringList=new ArrayList<Float[]>();
        for (int i = 0; i < str1.length; i++) {
            String[] x=str1[i].trim().split(" ");
            stringList.add(new Float[]{Float.parseFloat(x[0]),Float.parseFloat(x[1])});
        }

        geometryShape.put("type", "Circle");
        geometryShape.put("coordinates", stringList);
    return geometryShape;
    }


    /**
     * geo空间类型转openlayer：多边形
     * @param geoPolyGon
     * @return
     */
    public static Map<String, Object> polygon2OL(String geoPolyGon) {
        String geoCurvePolygonPattern = "CURVEPOLYGON \\(COMPOUNDCURVE \\(CIRCULARSTRING \\(((.*?))\\)\\)\\)";
        String geoPolygonPattern = "POLYGON \\(\\((.*?)\\)\\)";
        Map<String, Object> geometryShape=new HashMap<String, Object>();
        if(null==geoPolyGon||"".equals(geoPolyGon)){
            return null;
        }
        String curveResult = new GeometryUtil().getSubUtilSimple(geoPolyGon, geoCurvePolygonPattern);
        if("".equals(curveResult)){//找不到圆的点位数据
            String result = new GeometryUtil().getSubUtilSimple(geoPolyGon, geoPolygonPattern);
            String[] str1 = result.split(",");
            List<Float[]> stringList=new ArrayList<Float[]>();
            for (int i = 0; i < str1.length; i++) {
                String[] x=str1[i].trim().split(" ");
                stringList.add(new Float[]{Float.parseFloat(x[0]),Float.parseFloat(x[1])});
            }
            List<List<Float[]>>  shapeList=new ArrayList<>();
            shapeList.add(stringList);
            geometryShape.put("type", "Polygon");
            geometryShape.put("coordinates", shapeList);
        }
        else {
            geometryShape = circle2OL(geoPolyGon);
        }
        return  geometryShape;
    }

    /**
     * 返回单个字符串，若匹配到多个的话就返回第一个，方法与getSubUtil一样
     *
     * @param soap
     * @param rgex
     * @return
     */
    public String getSubUtilSimple(String soap, String rgex) {
        Pattern pattern = Pattern.compile(rgex);// 匹配的模式
        Matcher m = pattern.matcher(soap);
        while (m.find()) {
            return m.group(1);
        }
        return "";
    }

    /**
     * jsonList转geojson格式的list
     * @param jsonlist
     * @param shapeType  "point,line,polygon",指定要转换的类型
     * @param <T>
     * @return
     */
    public static <T> List<GeoJsonObj> shapeListToGeoJsonList(List<T>  jsonlist, String shapeType){
        List<Map<String, Object>> mapList= ListUtil.listConvert(jsonlist);
        return shapeMapToGeoJsonList(mapList, shapeType);
    }


    /**
     * jsonList转geojson格式的list
     * @param jsonlist
     * @param shapeType  "point,line,polygon",指定要转换的类型
     * @param <T>
     * @return
     */
    public   static <T> List<GeoJsonObj> shapeListToGeoJsonList(T  jsonlist,String shapeType){
        List<T> list = new ArrayList<>();
        list.add(jsonlist);
        List<Map<String, Object>> mapList= ListUtil.listConvert(list);
        return shapeMapToGeoJsonList(mapList, shapeType);
    }

    /**
     * jsonMap转geojson格式的list
     * @param jsonlist
     * @param shapeType
     * @return
     */
    public static List<GeoJsonObj> shapeMapToGeoJsonList(List<Map<String, Object>>  jsonlist, String shapeType){
        List<GeoJsonObj> geoJsonObjList=new ArrayList<>();
        for(Map<String, Object> objectMap:jsonlist){
            GeoJsonObj geoJsonObj=new GeoJsonObj();
            for (Map.Entry<String, Object> entry : objectMap.entrySet()) {
                if("shape".equals(entry.getKey())){
                    Map<String, Object> geometryShape=new HashMap<String, Object>();
                    if (objectMap.get("shape") == null) {
                        continue;
                    }
                    String olshape=objectMap.get("shape").toString();
                    switch (shapeType) {
                        case "point":
                            geometryShape=geoPoint2OL(olshape);
                            break;
                        case "line":
                            geometryShape=geoLine2OL(olshape);
                            break;
                        case "polygon":
                            geometryShape= polygon2OL(olshape);
                            break;
                        case "multiPolygon":
                            geometryShape= multiPolygon2OL(olshape);
                            break;

                        case "multiPoint":
                            geometryShape= geoMultiPoint2OL(olshape);
                            break;
                        default:
                            break;
                    }
                    geoJsonObj.setGeometry(geometryShape);
                }else{
                            geoJsonObj.putProperties(entry.getKey(), entry.getValue());
                }
            }
            geoJsonObjList.add(geoJsonObj);
        }
        return geoJsonObjList;
    }

    private static Map<String, Object> geoMultiPoint2OL(String olshape) {

        Map<String, Object> geometryShape=new HashMap<String, Object>();
        if(null==olshape||"".equals(olshape)){
            return null;
        }
        String geoMultPointPattern = "MULTIPOINT \\(\\((.*?)\\)\\)";
        String multResult = new GeometryUtil().getSubUtilSimple(olshape, geoMultPointPattern);

        String[] str1 = multResult.split("\\), \\(");
        List<Float[]>  shapeList=new ArrayList<>();
        for (int i = 0; i < str1.length; i++) {
            String[] x=str1[i].trim().split(" ");
            shapeList.add(new Float[]{Float.parseFloat(x[0]),Float.parseFloat(x[1])});
        }
        geometryShape.put("type", "MultiPoint");
        geometryShape.put("coordinates", shapeList);

        return geometryShape;
    }

    private static Map<String, Object> multiPolygon2OL(String olshape) {
        Map<String, Object> geometryShape=new HashMap<String, Object>();
        if(null==olshape||"".equals(olshape)){
            return null;
        }
        String geoMultiPolygonPattern = "MULTIPOLYGON \\(\\(\\((.*?)\\)\\)\\)";
        String multResult = new GeometryUtil().getSubUtilSimple(olshape, geoMultiPolygonPattern);
        String[] str1 = multResult.split("\\)\\), \\(\\(");
        if (str1.length == 1 ) {
            List<List<List<Float[]>>>  newShapeList = new ArrayList<>();
            str1 = multResult.split("\\), \\(");
            List<List<Float[]>>  shapeList=new ArrayList<>();
            for (int i = 0; i < str1.length; i++) {
                List<Float[]> stringList=new ArrayList<Float[]>();
                String[] str2 = str1[i].split(",");
                for (int j = 0; j <str2.length ; j++) {
                    String[] x=str2[j].trim().split(" ");
                    stringList.add(new Float[]{Float.parseFloat(x[0]),Float.parseFloat(x[1])});
                }
                shapeList.add(stringList);
            }
            newShapeList.add(shapeList);
            geometryShape.put("type", "MultiPolygon");
            geometryShape.put("coordinates", newShapeList);
        } else {
            List<List<List<Float[]>>>  shapeList=new ArrayList<>();
            List<List<Float[]>>  newShape =new ArrayList<>();
            for (int i = 0; i < str1.length; i++) {
                List<Float[]> stringList=new ArrayList<Float[]>();
                String[] str2 = str1[i].split(",");
                for (int j = 0; j <str2.length ; j++) {
                    String[] x=str2[j].trim().split(" ");
                    stringList.add(new Float[]{Float.parseFloat(x[0]),Float.parseFloat(x[1])});
                }
                newShape.add(stringList);
            }
            shapeList.add(newShape);
            geometryShape.put("type", "MultiPolygon");
            geometryShape.put("coordinates", shapeList);
        }

        return geometryShape;

    }


  /*  public static void main(String[] args) {
        String geoPoint = "POINT (64535.7895 45478.8856000006)";
        String geoLine = "LINESTRING(64709.9718236697 42911.3348856955,64685.6652999967 42911.0903999954,64677.4645999968 42910.8811999932,64676.7936999947 42910.8640999943,64673.2231999934 42910.7729999945)";
        String geoMultLine = "MULTILINESTRING ((66855.3304999992 43592.6488999948, 66855.3360999972 43592.5007999986, 66856.0900999978 43584.6951999962, 66858.6576999947 43558.1162999943, 66860.5083999932 43508.9419999942, 66863.2632999942 43435.7412, 66865.3542999998 43371.2130999938, 66865.3445999995 43370.4565999955), (66865.3583999947 43370.4555999935, 66865.3351999968 43369.7236999944, 66865.3256999999 43368.9868000001, 66865.3152999952 43368.1824999973, 66865.3049999997 43367.3780999929))";
        String olPointString = "{ \"type\": \"Feature\", \"properties\": { \"id\": \"81f73154-880c-018a-e905-40b43b1d3cbe\", " +
                "\"name\": \"园区城管大厦\", \"direction\": \"东\", \"lat\": 31.32575, \"lon\": 120.72887 }, " +
                "\"geometry\": { \"type\": \"Point\", \"coordinates\": [ 120.72887, 31.32575 ] }";
        String polyString = "POLYGON ((65604.1801399877 43942.942427313, 65408.4979808815 55063.7712425366, 65377.4326171884 55030.5374145526, 65334.3229980478 54983.1481933631, 65604.1801399877 43942.942427313))";
        String circle = "CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (63213.8233000003 48260.2443000004, 62786.9645573892 47833.3855571161, 63213.8233002735 47406.5268145051, 63640.6820428846 47833.3855573893, 63213.8233000003 48260.2443000004)))";
        String olLineString = "";
//        Map<String, Object> geometryShape= polygon2OL(polyString);
//        Map<String, Object> geometryShape= geoLine2OL(geoMultLine);
        Map<String, Object> geometryShape= circle2OL(circle);
    }*/
}
